﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace iNet.Media.Video
{
	/// <summary>
	/// ISO Base Media File 中繼資料介面。
	/// </summary>
	public interface IIsoBaseMediaFileMetadata : IMetadata
	{
		/// <summary>
		/// 取得中繼資料項目列表。
		/// </summary>
		IList<IbmfMetadataItem> MetadataItems { get; }
	}
	#region IsoBaseMediaFileMetadata
	/// <summary>
	/// 實作 IIsoBaseMediaFileMetadata 介面的中繼資料。
	/// </summary>
	public class IsoBaseMediaFileMetadata : MetadataBase, IIsoBaseMediaFileMetadata, IVideoMetadata
	{
		#region 欄位
		readonly Dictionary<uint, IbmfMetadataItem> _MetadataItems = new Dictionary<uint, IbmfMetadataItem>();
		IList<IbmfMetadataItem> _MetadataItemList;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 IsoBaseMediaFileMetadata 執行個體。
		/// </summary>
		/// <param name="items">中繼資料項目。</param>
		/// <param name="isReadOnly">是否為唯讀。</param>
		public IsoBaseMediaFileMetadata(IEnumerable<IbmfMetadataItem> items, bool isReadOnly)
			: base(null, isReadOnly)
		{
			if (items != null)
			{
				foreach (IbmfMetadataItem item in items)
				{
					if (item != null)
						_MetadataItems[item.ID] = item;
				}
			}
			if (isReadOnly)
				_MetadataItemList = new ReadOnlyCollection<IbmfMetadataItem>(_MetadataItems.Values.ToArray<IbmfMetadataItem>());
			else
			{
				_MetadataItemList = new ObservableCollection<IbmfMetadataItem>(_MetadataItems.Values);
				(_MetadataItemList as INotifyCollectionChanged).CollectionChanged += this.OnMetadataItemListChanged;
			}
		}
		#endregion
		#region Authors
		/// <summary>
		/// 取得或設定影片作者名稱。
		/// </summary>
		public override string[] Authors
		{
			get
			{
				string[] authorList = this.GetDataArrayFromMicrosoftItem<string>("WM/Writer");
				if (authorList != null)
					return authorList;
				string author = this.GetStringFromAppleItem(0xa9777274); //0xA9 + wrt
				if (author != null)
					return new string[] { author };
				return null;
			}
			set
			{
				this.SetDataToMicrosoftItem<string[]>("WM/Writer", value);
			}
		}
		#endregion
		#region Clone
		/// <summary>
		/// 建立可修改的 IsoBaseMediaFileMetadata 副本。
		/// </summary>
		/// <returns>IsoBaseMediaFileMetadata 副本。</returns>
		public override object Clone()
		{
			return new IsoBaseMediaFileMetadata(_MetadataItems.Values, false);
		}
		#endregion
		#region Comment
		/// <summary>
		/// 取得或設定媒體的註解文字。
		/// </summary>
		public override string Comment
		{
			get
			{
				return this.GetStringFromAppleItem(0xa9636d74);	//0xA9 + cmt
			}
			set
			{
				this.SetStringToAppleItem(0xa9636d74, value);
			}
		}
		#endregion
		#region Copyright
		/// <summary>
		/// 取得或設定媒體的版權資訊。
		/// </summary>
		public override string Copyright
		{
			get
			{
				return this.GetStringFromAppleItem(0xa9637079);	//0xA9 + cpy
			}
			set
			{
				this.SetStringToAppleItem(0xa9637079, value);
			}
		}
		#endregion
		#region CreatedYear
		/// <summary>
		/// 取得或設定影片建立年份。
		/// </summary>
		public virtual int? CreatedYear
		{
			get
			{
				string value = this.GetStringFromAppleItem(0xa9646179);	//0xA9 + day
				int year;
				if (value != null && int.TryParse(value, out year) && year >= 0)
					return year;
				return null;
			}
			set
			{
				this.SetStringToAppleItem(0xa9646179, (value != null ? value.Value.ToString() : null));
			}
		}
		#endregion
		#region Directors
		/// <summary>
		/// 取得或設定導演名稱。
		/// </summary>
		public virtual string[] Directors
		{
			get
			{
				return this.GetDataArrayFromMicrosoftItem<string>("WM/Director");
			}
			set
			{
				this.SetDataToMicrosoftItem<string[]>("WM/Director", value);
			}
		}
		#endregion
		#region Encoder
		/// <summary>
		/// 取得或設定編碼者名稱。
		/// </summary>
		public virtual string Encoder
		{
			get
			{
				string encoder = this.GetDataFromMicrosoftItem<string>("WM/EncodedBy");
				if (encoder != null)
					return encoder;
				return this.GetStringFromAppleItem(0xa9746f6f); //0xA9 + coo
			}
			set
			{
				this.SetDataToMicrosoftItem<string>("WM/EncodedBy", value);
			}
		}
		#endregion
		#region GetAsReadOnly
		/// <summary>
		/// 取得唯讀中繼資料。
		/// </summary>
		/// <returns>唯讀中繼資料。</returns>
		public override IMetadata GetAsReadOnly()
		{
			if (this.IsReadOnly)
				return this;
			return new IsoBaseMediaFileMetadata(_MetadataItems.Values, true);
		}
		#endregion
		#region GetDataArrayFromMicrosoftItem
		T[] GetDataArrayFromMicrosoftItem<T>(string name)
		{
			MicrosoftIbmfMetadataItem item = this.GetMetadataItem(0x58747261u) as MicrosoftIbmfMetadataItem;
			if (item != null)
				return item.GetDataArray<T>(name);
			return null;
		}
		#endregion
		#region GetDataFromMicrosoftItem
		T GetDataFromMicrosoftItem<T>(string name)
		{
			MicrosoftIbmfMetadataItem item = this.GetMetadataItem(0x58747261u) as MicrosoftIbmfMetadataItem;
			if (item != null)
				return item.GetData<T>(name);
			return default(T);
		}
		#endregion
		#region GetMetadataItem
		/// <summary>
		/// 取得指定識別碼的中繼資料項目。
		/// </summary>
		/// <param name="id">項目的識別碼。</param>
		/// <returns>指定識別碼的中繼資料項目，Null (Visual Basic 為 Nothing) 表示沒有符合指定識別碼的項目。</returns>
		protected IbmfMetadataItem GetMetadataItem(uint id)
		{
			IbmfMetadataItem item;
			_MetadataItems.TryGetValue(id, out item);
			return item;
		}
		#endregion
		#region GetStringFromAppleItem
		string GetStringFromAppleItem(uint id)
		{
			AppleIbmfMetadataItem item = this.GetMetadataItem(id) as AppleIbmfMetadataItem;
			return (item != null ? item.GetStringData() : null);
		}
		#endregion
		#region Keywords
		/// <summary>
		/// 取得或設定媒體的關鍵字。
		/// </summary>
		public override string[] Keywords
		{
			get
			{
				return this.GetDataArrayFromMicrosoftItem<string>("WM/Category");
			}
			set
			{
				this.SetDataToMicrosoftItem<string[]>("WM/Category", value);
			}
		}
		#endregion
		#region MetadataItems
		/// <summary>
		/// 取得中繼資料項目列表。
		/// </summary>
		public IList<IbmfMetadataItem> MetadataItems
		{
			get
			{
				return _MetadataItemList;
			}
		}
		#endregion
		#region OnMetadataItemListChanged
		void OnMetadataItemListChanged(object sender, NotifyCollectionChangedEventArgs e)
		{
			switch (e.Action)
			{
				case NotifyCollectionChangedAction.Add:
					foreach (IbmfMetadataItem item in e.NewItems)
					{
						if (item == null || _MetadataItems.ContainsKey(item.ID))
							throw new ArgumentException();
						_MetadataItems[item.ID] = item;
					}
					break;
				case NotifyCollectionChangedAction.Remove:
					foreach (IbmfMetadataItem item in e.OldItems)
						_MetadataItems.Remove(item.ID);
					break;
				case NotifyCollectionChangedAction.Replace:
					foreach (IbmfMetadataItem item in e.OldItems)
						_MetadataItems.Remove(item.ID);
					foreach (IbmfMetadataItem item in e.NewItems)
					{
						if (item == null || _MetadataItems.ContainsKey(item.ID))
							throw new ArgumentException();
						_MetadataItems[item.ID] = item;
					}
					break;
				default:
					_MetadataItems.Clear();
					foreach (IbmfMetadataItem item in _MetadataItemList)
					{
						if (item == null || _MetadataItems.ContainsKey(item.ID))
							throw new ArgumentException();
						_MetadataItems[item.ID] = item;
					}
					break;
			}
		}
		#endregion
		#region Performers
		/// <summary>
		/// 取得或設定演出者名稱。
		/// </summary>
		public virtual string[] Performers
		{
			get
			{
				string rawValue = this.GetStringFromAppleItem(0xa9415254); //0xA9 + ART
				if (rawValue != null)
					return rawValue.Split('/');
				return null;
			}
			set
			{
				if (value != null && value.Length > 0)
				{
					StringBuilder rawValue = new StringBuilder();
					for (int i = 0; i < value.Length; ++i)
					{
						if (rawValue.Length > 0)
							rawValue.Append('/');
						string name = value[i];
						if (string.IsNullOrEmpty(name))
							continue;
						rawValue.Append(name.Replace('/', ' '));
					}
					this.SetStringToAppleItem(0xa9415254, rawValue.ToString());
				}
				else
					this.RemoveMetadataItem(0xa9415254);
			}
		}
		#endregion
		#region Producers
		/// <summary>
		/// 取得或設定製作人名稱。
		/// </summary>
		public virtual string[] Producers
		{
			get
			{
				return this.GetDataArrayFromMicrosoftItem<string>("WM/Producer");
			}
			set
			{
				this.SetDataToMicrosoftItem<string[]>("WM/Producer", value);
			}
		}
		#endregion
		#region Publisher
		/// <summary>
		/// 取得或設定發行者名稱。
		/// </summary>
		public virtual string Publisher
		{
			get
			{
				return this.GetDataFromMicrosoftItem<string>("WM/Publisher");
			}
			set
			{
				this.SetDataToMicrosoftItem<string>("WM/Publisher", value);
			}
		}
		#endregion
		#region Rating
		/// <summary>
		/// 取得或設定媒體的評價。
		/// </summary>
		public override int? Rating
		{
			get
			{
				return this.GetDataFromMicrosoftItem<int?>("WM/SharedUserRating");
			}
			set
			{
				this.SetDataToMicrosoftItem<int?>("WM/SharedUserRating", value);
			}
		}
		#endregion
		#region RatingPercentage
		/// <summary>
		/// 取得或設定媒體的評價百分比。
		/// </summary>
		public override int? RatingPercentage
		{
			get
			{
				int? rating = this.Rating;
				if (rating != null)
				{
					int percentage = rating.Value;
					if (percentage >= 0 && percentage <= 100)
						return percentage;
				}
				return null;
			}
			set
			{
				int rating = value.GetValueOrDefault();
				if (rating < 0 || rating > 100)
					throw new ArgumentOutOfRangeException();
				this.Rating = value;
			}
		}
		#endregion
		#region RemoveMetadataItem
		/// <summary>
		/// 移除指定的中繼資料項目。
		/// </summary>
		/// <param name="id">指定移除的項目識別碼。</param>
		/// <returns>項目移除是否成功。</returns>
		/// <exception cref="InvalidOperationException">中繼資料為唯讀。</exception>
		protected bool RemoveMetadataItem(uint id)
		{
			if (this.IsReadOnly)
				throw new InvalidOperationException();
			IbmfMetadataItem item;
			if (_MetadataItems.TryGetValue(id, out item))
			{
				_MetadataItemList.Remove(item);
				return true;
			}
			return false;
		}
		#endregion
		#region RemoveMetadataItems
		/// <summary>
		/// 移除指定的中繼資料項目。
		/// </summary>
		/// <param name="idList">指定移除的項目識別碼。</param>
		/// <returns>移除的項目個數。</returns>
		/// <exception cref="InvalidOperationException">中繼資料為唯讀。</exception>
		protected int RemoveMetadataItems(IList<uint> idList)
		{
			if (this.IsReadOnly)
				throw new InvalidOperationException();
			int result = 0;
			if (idList != null)
			{
				for (int i = idList.Count - 1; i >= 0; --i)
				{
					IbmfMetadataItem item;
					if (_MetadataItems.TryGetValue(idList[i], out item))
					{
						++result;
						_MetadataItemList.Remove(item);
					}
				}
			}
			return result;
		}
		#endregion
		#region SetDataToMicrosoftItem
		void SetDataToMicrosoftItem<T>(string name, T data)
		{
			if (this.IsReadOnly)
				throw new InvalidOperationException();
			MicrosoftIbmfMetadataItem item = this.GetMetadataItem(0x58747261u) as MicrosoftIbmfMetadataItem;
			if (item == null)
			{
				item = new MicrosoftIbmfMetadataItem(null);
				this.SetMetadataItem(item);
			}
			if (data != null)
				item.SetData<T>(name, data);
			else
				item.RemoveData(name);
		}
		#endregion
		#region SetMetadataItem
		/// <summary>
		/// 加入指定的中繼資料項目。
		/// </summary>
		/// <param name="item">指定的中繼資料項目。若中繼資料項目識別碼重複，則原有的項目將被覆蓋。</param>
		/// <exception cref="ArgumentNullException">item 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="InvalidOperationException">中繼資料為唯讀。</exception>
		protected void SetMetadataItem(IbmfMetadataItem item)
		{
			if (item == null)
				throw new ArgumentNullException("item");
			if (this.IsReadOnly)
				throw new InvalidOperationException();
			IbmfMetadataItem currentItem;
			if (_MetadataItems.TryGetValue(item.ID, out currentItem))
				_MetadataItemList.Remove(currentItem);
			_MetadataItemList.Add(item);
		}
		#endregion
		#region SetStringToAppleItem
		void SetStringToAppleItem(uint id, string value)
		{
			if (value != null)
				this.SetMetadataItem(new AppleIbmfMetadataItem(id, AppleIbmfMetadataItemType.Text, value));
			else
				this.RemoveMetadataItem(id);
		}
		#endregion
		#region Title
		/// <summary>
		/// 取得或設定媒體的標題。
		/// </summary>
		public override string Title
		{
			get
			{
				return this.GetStringFromAppleItem(0xa96e616d);	//0xA9 + nam
			}
			set
			{
				this.SetStringToAppleItem(0xa96e616d, value);
			}
		}
		#endregion
	}
	#endregion
	#region IbmfMetadataItem
	/// <summary>
	/// 表示一個 ISO Base Media File 中繼資料項目。
	/// </summary>
	public abstract class IbmfMetadataItem
	{
		#region 欄位
		readonly uint _ID;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 IbmfMetadataItem 執行個體。
		/// </summary>
		/// <param name="name">項目的識別碼。</param>
		protected IbmfMetadataItem(uint id)
		{
			_ID = id;
		}
		#endregion
		#region ID
		/// <summary>
		/// 取得項目的識別碼。
		/// </summary>
		public uint ID
		{
			get
			{
				return _ID;
			}
		}
		#endregion
		#region RawData
		/// <summary>
		/// 取得原始封裝在 Box 中的資料。
		/// </summary>
		public abstract byte[] RawData { get; }
		#endregion
	}
	#endregion
	#region AppleIbmfMetadataItem
	/// <summary>
	/// 表示一個 Apple ISO Base Media File 中繼資料項目。
	/// </summary>
	public class AppleIbmfMetadataItem : IbmfMetadataItem
	{
		#region 欄位
		readonly byte[] _Data;
		readonly AppleIbmfMetadataItemType _Type;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 AppleIbmfMetadataItem 執行個體。
		/// </summary>
		/// <param name="id">項目的識別碼。</param>
		/// <param name="type">項目資料類型。</param>
		/// <param name="data">項目資料內容。</param>
		public AppleIbmfMetadataItem(uint id, AppleIbmfMetadataItemType type, byte[] data)
			: base(id)
		{
			_Type = type;
			_Data = data;
		}
		/// <summary>
		/// 初始化新的 AppleIbmfMetadataItem 執行個體。
		/// </summary>
		/// <param name="id">項目的識別碼。</param>
		/// <param name="type">項目資料類型。</param>
		/// <param name="data">項目的文字資料內容。</param>
		public AppleIbmfMetadataItem(uint id, AppleIbmfMetadataItemType type, string data)
			: base(id)
		{
			_Type = type;
			_Data = (string.IsNullOrEmpty(data) ? null : Encoding.UTF8.GetBytes(data));
		}
		#endregion
		#region FromRawData
		/// <summary>
		/// 從原始的 Box 資料建立新的 AppleIbmfMetadataItem 執行個體。
		/// </summary>
		/// <param name="boxType">Box 類型。</param>
		/// <param name="boxData">Box 資料。</param>
		/// <returns>新的 AppleIbmfMetadataItem 執行個體。</returns>
		/// <exception cref="ArgumentException">Box 資料格式錯誤。</exception>
		/// <exception cref="ArgumentNullException">boxData 為 Null (Visual Basic 為 Nothing)。</exception>
		public static AppleIbmfMetadataItem FromRawData(uint boxType, byte[] boxData)
		{
			//確認參數
			if (boxData == null)
				throw new ArgumentNullException("boxData");

			//確認資料長度
			if (boxData.Length < 16)
				throw new ArgumentException();
			int boxLength = BitConverter.BigEndian.ToInt32(boxData);
			if (boxLength < 16)
				throw new ArgumentException();

			//確認 Box 名稱
			if (BitConverter.BigEndian.ToUInt32(boxData, 4) != 0x64617461u)
				throw new ArgumentException();

			//取得資料類型
			AppleIbmfMetadataItemType type = (AppleIbmfMetadataItemType)BitConverter.BigEndian.ToInt32(boxData, 8);

			//取得原始資料
			int dataLength = (boxLength - 16);
			byte[] data = new byte[dataLength];
			if (dataLength > 0)
				Array.Copy(boxData, 16, data, 0, dataLength);

			//建立項目
			return new AppleIbmfMetadataItem(boxType, type, data);
		}
		#endregion
		#region GetStringData
		/// <summary>
		/// 將項目資料轉成對應的字串。
		/// </summary>
		/// <returns>表示項目內容的字串。</returns>
		public string GetStringData()
		{
			if (_Data != null && _Data.Length > 0)
				return Encoding.UTF8.GetString(_Data);
			return null;
		}
		#endregion
		#region RawData
		/// <summary>
		/// 取得原始封裝在 Box 中的資料。
		/// </summary>
		public override byte[] RawData
		{
			get
			{
				//取得資料長度
				int dataLength = (_Data != null ? _Data.Length : 0);

				//建立 data Box
				byte[] boxData = new byte[dataLength + 16];
				BitConverter.BigEndian.GetBytes((uint)boxData.Length, boxData, 0);
				BitConverter.BigEndian.GetBytes(0x64617461u, boxData, 4);
				BitConverter.BigEndian.GetBytes((int)_Type, boxData, 8);
				if (dataLength > 0)
					Array.Copy(_Data, 0, boxData, 16, dataLength);

				//完成
				return boxData;
			}
		}
		#endregion
	}
	#endregion
	#region AppleIbmfMetadataItemType
	/// <summary>
	/// 表示 Apple ISO Base Media File 中繼資料項目的類型。
	/// </summary>
	public enum AppleIbmfMetadataItemType
	{
		/// <summary>
		/// 一般資料。
		/// </summary>
		Data = 0x0,
		/// <summary>
		/// 文字資料。
		/// </summary>
		Text = 0x1,
		/// <summary>
		/// 影像資料。
		/// </summary>
		Image = 0xD,
	}
	#endregion
	#region MicrosoftIbmfMetadataItem
	/// <summary>
	/// 表示一個 Microsoft ISO Base Media File 中繼資料項目。
	/// </summary>
	public class MicrosoftIbmfMetadataItem : IbmfMetadataItem
	{
		#region 欄位
		readonly Dictionary<string, object> _Data = new Dictionary<string, object>();
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化新的 MicrosoftIbmfMetadataItem 執行個體。
		/// </summary>
		/// <param name="data">項目所包含的子資料。</param>
		public MicrosoftIbmfMetadataItem(IDictionary<string, object> data)
			: base(0x58747261u)
		{
			if (data != null)
			{
				foreach (KeyValuePair<string, object> pair in data)
					_Data[pair.Key] = pair.Value;
			}
		}
		#endregion
		#region FromRawData
		/// <summary>
		/// 從原始的 Box 資料建立 Microsoft ISO Base Media File 中繼資料項目。
		/// </summary>
		/// <param name="boxData">Box 資料內容。</param>
		/// <returns>Microsoft ISO Base Media File 中繼資料項目。</returns>
		/// <exception cref="ArgumentNullException">boxData 為 Null (Visual Basic 為 Nothing)。</exception>
		public static MicrosoftIbmfMetadataItem FromRawData(byte[] boxData)
		{
			//確認參數
			if (boxData == null)
				throw new ArgumentNullException("boxData");
			
			//讀取資料內容
			Dictionary<string, object> data = new Dictionary<string, object>();
			int offset = 0;
			while (offset < boxData.Length)
			{
				//確認剩餘資料量
				if (offset + 8 >= boxData.Length)
					break;

				//取得項目總長度
				int itemLength = BitConverter.BigEndian.ToInt32(boxData, offset);
				int itemEndOffset = offset + itemLength;
				if (itemLength <= 0 || itemEndOffset > boxData.Length)
					break;

				//取得名稱長度
				int nameLength = BitConverter.BigEndian.ToInt32(boxData, offset + 4);
				if (nameLength < 0 || nameLength + 4 > itemLength)
					break;

				//取得名稱
				string name = Encoding.Default.GetString(boxData, offset + 8, nameLength);

				//取得資料個數
				int dataOffset = (offset + 8 + nameLength);
				int dataCount = BitConverter.BigEndian.ToInt32(boxData, dataOffset);
				if (dataCount < 0)
					break;
				dataOffset += 4;

				//讀取項目資料
				object[] array = new object[dataCount];
				for (int i = 0; i < dataCount; ++i)
				{
					//取得單一資料長度
					int dataLength = BitConverter.BigEndian.ToInt32(boxData, dataOffset);
					if (dataLength < 6 || dataOffset + dataLength > itemEndOffset)
						break;
					dataOffset += 4;

					//取得資料格式
					int dataType = BitConverter.BigEndian.ToUInt16(boxData, dataOffset);
					dataOffset += 2;

					//讀取資料
					dataLength -= 6;
					if (dataLength > 0)
					{
						byte[] rawData = new byte[dataLength];
						Array.Copy(boxData, dataOffset, rawData, 0, dataLength);
						try
						{
							switch (dataType)
							{
								case 0x13:	//Int32
									array[i] = BitConverter.LittleEndian.ToInt32(rawData);
									break;
								case 0x08:	//String
									if (dataLength > 2)
										array[i] = Encoding.Unicode.GetString(rawData, 0, dataLength - 2);
									else
										array[i] = "";
									break;
								default:	//未知
									array[i] = rawData;
									break;
							}
						}
						catch
						{
							array[i] = rawData;
						}
					}
					dataOffset += dataLength;
				}
				data[name] = array;

				//移動至下一個項目
				offset += itemLength;
			}

			//建立項目
			return new MicrosoftIbmfMetadataItem(data);
		}
		#endregion
		#region GetData
		/// <summary>
		/// 取得項目中指定名稱的資料。
		/// </summary>
		/// <typeparam name="T">資料型別。</typeparam>
		/// <param name="name">資料名稱。</param>
		/// <returns>指定名稱的資料，若無法找到符合的資料則傳回該型別的預設值。</returns>
		public T GetData<T>(string name)
		{
			object rawValue;
			if (_Data.TryGetValue(name, out rawValue))
			{
				Array array = (rawValue as Array);
				if (array != null)
				{
					if (array.Length == 0)
						return default(T);
					rawValue = array.GetValue(0);
				}
				T value;
				if (rawValue.TryCast<T>(out value))
					return value;
			}
			return default(T);
		}
		#endregion
		#region GetDataArray
		/// <summary>
		/// 取得項目中指定名稱的資料陣列。
		/// </summary>
		/// <typeparam name="T">陣列元素型別。</typeparam>
		/// <param name="name">資料名稱。</param>
		/// <returns>指定名稱的資料陣列，若無法找到符合的資料則傳回 Null (Visual Basic 為 Nothing)。</returns>
		public T[] GetDataArray<T>(string name)
		{
			object rawValue;
			if (_Data.TryGetValue(name, out rawValue))
			{
				T[] array = null;
				if (rawValue is Array)
				{
					if (rawValue.TryCastToArray<T>(out array))
						return array;
					return null;
				}
				T value;
				if (rawValue.TryCast<T>(out value))
					return new T[] { value };
			}
			return null;
		}
		#endregion

		#region RawData

		public override byte[] RawData
		{
			get { throw new NotImplementedException(); }
		}
		#endregion
		#region RemoveData
		/// <summary>
		/// 移除指定名稱的資料。
		/// </summary>
		/// <param name="name">欲移除的資料名稱。</param>
		/// <returns>True 表示移除完成，False 表示指定的名稱不在項目中。</returns>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		public bool RemoveData(string name)
		{
			if (name == null)
				throw new ArgumentNullException("name");
			return _Data.Remove(name);
		}
		#endregion
		#region SetData
		/// <summary>
		/// 將指定名稱的資料存放置項目中。
		/// </summary>
		/// <typeparam name="T">資料型別。</typeparam>
		/// <param name="name">資料名稱。</param>
		/// <param name="data">指定的資料，Null (Visual Basic 為 Nothing) 表示移除這筆資料。</param>
		/// <exception cref="ArgumentNullException">name 為 Null (Visual Basic 為 Nothing)。</exception>
		public void SetData<T>(string name, T data)
		{
			//確認參數
			if (name == null)
				throw new ArgumentNullException("name");

			//設定資料
			if (data != null)
				_Data[name] = data;
			else
				_Data.Remove(name);
		}
		#endregion
	}
	#endregion
}
